#pragma once
#ifndef __LIT__FLAG__LIST__HH__
#define __LIT__FLAG__LIST__HH__

#include <LitExport.hpp>

namespace Lit
{
	template<typename FlagT>
	class FlagList
	{
	public:
		typename typedef FlagT					Type;
		typename typedef std::list<Type>		List;
		typename typedef FlagList<Type>			MyType;

		typename typedef List::iterator					iterator;
		typename typedef List::const_iterator			const_iterator;
		typename typedef List::reverse_iterator			reverse_iterator;
		typename typedef List::const_reverse_iterator	const_reverse_iterator;

	protected:
		List mFlags;

	public:
		FlagList(){}
		FlagList( const Type &type ){ mFlags.push_back( type ); }
		FlagList(const MyType& rk):mFlags(rk.mFlags){}
		~FlagList(){}
		
		List& flags(){ return mFlags; }
		const List& flags() const{ return mFlags; }
		
		iterator find( Type flag ){ for( iterator i=mFlags.begin(); i!=mFlags.end(); i++ ) if( *i == flag ) return i; return mFLags.end(); }
		const_iterator find( Type flag ) const{ for( iterator i=mFlags.begin(); i!=mFlags.end(); i++ ) if( *i == flag ) return i; return mFLags.end(); }
		reverse_iterator rfind( Type flag ){ for( iterator i=mFlags.rbegin(); i!=mFlags.rend(); i++ ) if( *i == flag ) return i; return mFLags.end(); }
		const_reverse_iterator rfind( Type flag ) const{ for( iterator i=mFlags.rbegin(); i!=mFlags.rend(); i++ ) if( *i == flag ) return i; return mFLags.end(); }
		
		MyType& operator <<( const Type& rk ){enable( rk );return *this;}
		MyType& operator <<( const MyType& rk ){enable( rk );return *this;}

		MyType& operator +=( const MyType& rk ){enable( rk );return *this;}
		MyType& operator +=( const Type& rk ){enable( rk );return *this;}

		MyType& operator -=( const Type& rk ){disable( rk );return *this;}
		MyType& operator -=( const MyType& rk ){disable( rk );return *this;}

		bool empty() const{ return mFlags.empty(); }
		size_t size(){ return mFlags.size(); }
		void clear(){ mFlags.clear(); }
		
		void enable( const MyType& rk ){ for( auto i=rk.begin(); i!=rk.end(); i++ ) enable( *i ); }
		void disable( const MyType& rk ){ for( auto i=rk.begin(); i!=rk.end(); i++ ) disable( *i ); }
		void set( const MyType& lst, bool state ){ for( auto i=rk.begin(); i!=rk.end(); i++ ) setEnabled( *i, state ); }
		
		bool has( Type flag ) const
		{
			for( const_iterator i=mFlags.begin(); i!=mFlags.end(); i++ )
				if( *i == flag ) return true;
			return false;
		}

		void enable( Type flag )
		{
			iterator i=mFlags.begin();
			if( i == mFlags.end() ) mFlags.push_back( flag );
		}
		void disable( Type flag )
		{
			iterator i=mFlags.begin();
			if( i != mFlags.end() ) mFlags.erase( i );
		}
		void set( Type flag, bool state )
		{
			if( state ) enable( flag );
			else disable( flag );
		}

		FlagList& operator=( const FlagList& rk )
		{
			mFlags = rk.mFlags;
			return *this;
		}
	};
};

#endif